<template>
	<div class="it-road-container">
		<div id="itRoadContainer" style="position: relative"></div>
		<div id="miniMapId"></div>
		<div v-if="config.noDataFlag || itRoadData.nodes.length == 0" class="no-data">
			<svg-icon class-name="nodata" icon-class="nodata" style="width: 1.2rem"></svg-icon>
			<span style="margin-left: 5px">暂无数据</span>
		</div>
	</div>
</template>

<script setup name="YdItRoad" lang="tsx">
import { ref, reactive, computed, onBeforeMount, onMounted, nextTick } from 'vue';
import { G6GraphEvent } from '@antv/g6';
import G6 from '@antv/g6';
import registerLayout from './layout';
import registerShape from './shape';
import registerBehavior from './behavior';

import { ConfigType, GraphCustomOptionsType, GraphData } from './itRoad-type';

const props = defineProps<{
	config: ConfigType;
}>();

const $emit = defineEmits(['dragNode', 'afterRender', 'clickNode', 'dblclickNode', 'graphInited']);

// g6 graph对象
const graph = ref();
// 防抖
const debounce = reactive({
	// 频率(ms)
	time: 100,
	flag: true,
});
const clicktime = ref();
// 缩略图插件
const minimap = ref();

// IT路径图数据 nodes 节点，edges边
const itRoadData = reactive<GraphData>({
	nodes: [],
	edges: [],
});

// graph图 默认配置
let defaultOptions = reactive<GraphCustomOptionsType>({
	// 最小缩放比例
	minZoom: 0.5,
	// 最大缩放比例
	maxZoom: 2,
	// 布局配置项
	layout: {
		type: 'dagre',
		rankdir: 'LR',
		nodesep: 50,
		ranksep: 100,
	},
	modes: {
		// 默认模式
		defaultMode: [
			// 拖拽画布
			'drag-canvas',
			// 缩放画布
			'zoom-canvas',
			// 节点高亮(自定义)
			'activate-node',
		],
		edit: [
			// 拖拽画布
			'drag-canvas',
			// 缩放画布
			'zoom-canvas',
			// 拖拽节点
			'drag-node',
			// 节点高亮(自定义)
			'activate-node',
		],
		editNoDragNode: [
			// 拖拽画布
			'drag-canvas',
			// 缩放画布
			'zoom-canvas',
			// 节点高亮(自定义)
			'activate-node',
		],
	},

	// 渲染方式 canvas或者svg
	renderer: 'canvas',
	toolbarObj: undefined,
});
const nodeType = computed(() => {
	if (props.config.type) {
		return props.config.type;
	} else {
		return 'netWorkNode';
	}
});

// 加载自定义 布局、样式和文本、交互行为配置
Promise.all([registerLayout(G6, nodeType.value), registerShape(G6, nodeType.value), registerBehavior(G6, nodeType.value)])
	.then((res) => {
		$emit('graphInited');
		console.log('graph初始化完成--------------,', res);
	})
	.catch((e) => {
		console.log('e', e);
	});

// console.log('nodetype.value', nodeType.value);
onBeforeMount(async () => {
	// // 加载自定义 布局、样式和文本、交互行为配置
	// Promise.all([registerLayout(G6, nodeType.value), registerShape(G6, './SegmentOverview/node'), registerBehavior(G6, nodeType.value)])
	// 	.then((res) => {
	// 		$emit('graphInited');
	// 		console.log('graph初始化完成--------------,', res);
	// 	})
	// 	.catch((e) => {
	// 		console.log('e', e);
	// 	});
});
onMounted(() => {
	nextTick(() => {
		// 初始化
		// console.log('nexttick------------');
		initGraph();
	});
});

// 初始化
function initGraph() {
	// 配置项
	// let options = {};
	// 获取画布长宽
	let width = props.config.canvasWidth,
		height = props.config.canvasHeight;
	if (!width) {
		width = document.getElementById('itRoadContainer')!.scrollWidth - 1;
	}
	if (!height) {
		height = (document.documentElement.clientHeight || document.body.clientHeight) - 160;
	}
	let customOptions = props.config.customOptions;

	// 合并自定义配置项
	if (props.config.customOptions) {
		defaultOptions.minZoom = customOptions.minZoom || defaultOptions.minZoom;
		defaultOptions.maxZoom = customOptions.maxZoom || defaultOptions.maxZoom;
		defaultOptions.renderer = customOptions.renderer || defaultOptions.renderer;
		defaultOptions.layout = customOptions.layout || defaultOptions.layout;

		defaultOptions.modes!.defaultMode = customOptions.modes?.defaultMode || defaultOptions.modes?.defaultMode;
		defaultOptions.modes!.edit = customOptions.modes?.edit || defaultOptions.modes!.edit;
		defaultOptions.modes!.editNoDragNode = customOptions.modes?.editNoDragNode || defaultOptions.modes!.editNoDragNode;
		defaultOptions.toolbarObj = customOptions.toolbarObj;
		// defaultOptions = { ...defaultOptions, ...customOptions };
	}
	const graphObj = new G6.Graph({
		// 图的  DOM 容器，可以传入该 DOM 的 id 或者直接传入容器的 HTML 节点对象
		container: 'itRoadContainer',
		// 指定画布宽度，单位为 'px'
		width: width,
		// 指定画布高度，单位为 'px'
		height: height,
		// 是否开启画布自适应。开启后图自动适配画布大小
		fitView: true,
		// v3.5.1 后支持。开启后，图将会被平移，图的中心将对齐到画布中心，但不缩放。优先级低于 fitView
		fitCenter: true,
		// 最小缩放比例
		minZoom: defaultOptions.minZoom,
		// 最大缩放比例
		maxZoom: defaultOptions.maxZoom,
		// 渲染方式，该配置项除 V3.3.x 外其他版本均支持 'canvas' / 'svg'
		renderer: defaultOptions.renderer,
		// 是否启用 stack，即是否开启 redo & undo 功能，该配置项 V3.6 及以上版本支持
		// enabledStack: false,
		// 插件
		plugins: [],
		// 设置画布的模式
		modes: {
			// 默认模式
			default: defaultOptions.modes?.defaultMode,
			// 编辑模式
			edit: defaultOptions.modes?.edit,
			// 编辑模式-不拖动节点
			editNoDragNode: defaultOptions.modes?.editNoDragNode,
		},
		// 布局配置项，使用 type 字段指定使用的布局方式，type 可取以下值：random, radial, mds, circular, fruchterman, force, dagre，各布局详细的配置请参考
		layout: defaultOptions.layout,
		/* layout: {
            type: 'allItRoadLayout'
          }, */
		// 默认状态下节点的配置，比如 type, size, color。会被写入的 data 覆盖
		defaultNode: {
			type: nodeType.value,
		},
		// 默认状态下边的配置，比如 type, size, color。会被写入的 data 覆盖
		defaultEdge: {
			type: 'myCubicHorizontal',
		},
		// 各个状态下节点的样式，例如 hover、selected，3.1 版本新增
		nodeStateStyles: {},
		// 各个状态下边的样式，例如 hover、selected，3.1 版本新增
		edgeStateStyles: {},
	});
	graph.value = graphObj;
	// console.log('graphObj',graph.value.setState)
	// 默认加载的插件
	// toggleShowMinimap();

	if (defaultOptions.toolbarObj) {
		const toolbar = new G6.ToolBar(defaultOptions.toolbarObj!);
		graph.value.addPlugin(toolbar);
	}

	// 绑定事件
	// 1、拖拽
	graph.value.on('dragend', (ev: G6GraphEvent) => {
		// 防抖
		if (!checkDebounce()) {
			return;
		}
		if (!ev.item) {
			return;
		}
		$emit('dragNode', ev);
	});

	// 2、双击
	graph.value.on('dblclick', (ev: G6GraphEvent) => {
		clearTimeout(clicktime.value);
		// 防抖
		if (!checkDebounce()) {
			return;
		}
		if (!ev.item) {
			return;
		}
		$emit('dblclickNode', ev);
	});

	// 3、单击
	graph.value.on('click', (ev: G6GraphEvent) => {
		clearTimeout(clicktime.value);

		clicktime.value = setTimeout(() => {
			// 防抖
			if (!checkDebounce()) {
				return;
			}
			if (!ev.item) {
				return;
			}

			$emit('clickNode', ev);
		}, 300);
	});

	// 4、页面渲染完成
	graph.value.on('afterrender', () => {
		$emit('afterRender');
	});
}
// 加载IT路径图
function loadItRoadData(data: GraphData) {
	itRoadData.edges = data.edges;
	itRoadData.nodes = data.nodes;
	graph.value.read(itRoadData);
}
// 切换显示/隐藏缩略图
function toggleShowMinimap() {
	if (minimap.value) {
		graph.value.removePlugin(minimap.value);
		minimap.value = null;
	} else {
		// 缩略图
		minimap.value = new G6.Minimap({
			container: document.getElementById('miniMapId') as HTMLDivElement,
			size: [150, 100],
		});
		graph.value.addPlugin(minimap.value);
	}
}
// 设置画布模式
function setGraphMode(mode: any) {
	graph.value.setMode(mode);
}
// 设置布局
function setLayout(layout: any) {
	graph.value.updateLayout(layout);
}
// 设置节点状态
function setItemStateById(id: any, stateName: any, flags: boolean) {
	graph.value.setItemState(graph.value.findById(id), stateName, flags);
}

// 更新信息
function updateInfo(data: any) {
	const nodeMap: Record<string, any> = {};
	data.forEach((d: Record<string, any>) => {
		nodeMap[d.mapKey] = d;
	});
	const nodes = graph.value.getNodes();
	nodes.forEach((node: any) => {
		const nodeModel = JSON.parse(JSON.stringify(node.getModel()));
		const dbNode = nodeMap[nodeModel.id];
		if (dbNode && dbNode.status !== '1') {
			nodeModel.status = dbNode.status;
			nodeModel.text.reqCount = dbNode.reqCount + '';
			nodeModel.text.avgDealTime = dbNode.avgDealTime;
			nodeModel.text.health = dbNode.health;
			node.update(nodeModel);
		} else if (nodeModel.status === '1') {
			// 无数据，但不需要更新节点
		} else {
			// 无数据，要更新节点
			nodeModel.status = '1';
			nodeModel.text.reqCount = '0';
			nodeModel.text.avgDealTime = '-';
			nodeModel.text.health = '-';
			node.update(nodeModel);
		}
	});
}
// ture: 通过防抖检查
function checkDebounce() {
	if (debounce.flag) {
		debounce.flag = false;
		setTimeout(function () {
			debounce.flag = true;
		}, debounce.time);
		return true;
	}
	return false;
}
// 获取所有节点
function getAllNodes() {
	return graph.value.getNodes();
}

// 导出方法让父组件调用
defineExpose({
	setGraphMode,
	setLayout,
	setItemStateById,
	loadItRoadData,
	getAllNodes,
	updateInfo,
	toggleShowMinimap,
	graph: graph,
});
</script>
<style scoped>
:deep(.svg-icon) {
	width: 1.5em;
	height: 1.5em;
}
</style>
<style rel="stylesheet/scss" lang="scss">
#miniMapId {
	position: absolute;
	width: 150px;
	height: 100px;
	top: 0;
}

.no-data {
	position: absolute;
	left: 49%;
	top: 49%;
	color: #ffffff70;
	display: flex;
	align-items: center;
}

.it-road-container {
	position: relative;
	height: 100%;
	.g6-component-toolbar {
		left: unset;
		right: 0;
		padding: 0;
		background-color: #ffffff00;
		border: 0;
		color: #ffffff;
		height: 36px;
		display: flex;
		align-items: center;

		li {
			position: static;
		}

		i {
			font-size: 16px;
		}
	}
}
</style>
